// -------- Accounts Script --------
// ------ Created by VRocker -------

const LVL_UNREGISTERED = -1;
const LVL_REGISTERED = 0;

const LOGIN_ATTEMPTS = 3;

g_hashPasswords <- HashTable( "Passwords" );
g_hashLevels <- HashTable( "Levels" );
g_hashIPs <- HashTable( "IPs" );
g_hashAutologin <- HashTable( "Autologin" );

g_bannedNames <- [ "admin", "administrator", "nobody" ];
g_loggedIn <- array( 128 );
g_loginTimers <- array( 128 );

g_LoginAttempts <- array( 128 );

function LoadAccountHashes()
{
	g_hashPasswords.Load( "Hashes/Accounts/Passwords.hsh" );
	g_hashLevels.Load( "Hashes/Accounts/Levels.hsh" );
	g_hashIPs.Load( "Hashes/Accounts/IPs.hsh" );
	g_hashAutologin.Load( "Hashes/Accounts/Autologin.hsh" );
}

function SaveAccountHashes()
{
	g_hashPasswords.Save( "Hashes/Accounts/Passwords.hsh" );
	g_hashLevels.Save( "Hashes/Accounts/Levels.hsh" );
	g_hashIPs.Save( "Hashes/Accounts/IPs.hsh" );
	g_hashAutologin.Save( "Hashes/Accounts/Autologin.hsh" );
}

function CloseAccountHashes()
{
	g_hashPasswords.Close();
	g_hashLevels.Close();
	g_hashIPs.Close();
	g_hashAutologin.Close();
	
	g_hashPasswords <- null;
	g_hashLevels <- null;
	g_hashIPs <- null;
	g_hashAutologin <- null;
}

function DoLogin( plr, pass )
{
	if ( g_loggedIn[ plr.ID ] != true )
	{
		if ( pass )
		{
			if ( MD5( pass ) == GetPassword( plr.Name ) )
			{
				// Password correct, log them in!
				SetPlayerIP( plr.Name, plr.IP );

				g_loggedIn[ plr.ID ] = true;
				
				// Just incase they got a password wrong and then logout
				g_LoginAttempts[ plr.ID ] = 0;
			
				local level = GetPlayerLevel( plr );
				if ( level == LVL_REGISTERED )
					MessagePlayer( "You have been logged in.", plr );
				else
					MessagePlayer( "You have been logged in (Level: " + level + ").", plr );
		
				// Kill any timers that might exist
				local timer = g_loginTimers[ plr.ID ];
				if ( timer )
					timer.Delete();
			}
			else
			{
				// Wrong password
				// Give people 3 attempts to login
				g_LoginAttempts[ plr.ID ]++;
				if ( g_LoginAttempts[ plr.ID ] == LOGIN_ATTEMPTS )
				{
					Message( "Kicking " + plr.Name + " (Too many invalid passwords)" );
				
					local timer = g_loginTimers[ plr.ID ];
					if ( timer )
						timer.Delete();
					
					KickPlayer( plr );
		
					return;
				}
			
				if ( g_LoginAttempts[ plr.ID ] == LOGIN_ATTEMPTS-1 )
					MessagePlayer( "Incorrect password - 1 try remaining", plr, COL_CMDERROR );
				else
					MessagePlayer( "Incorrect password - " + (LOGIN_ATTEMPTS - g_LoginAttempts[ plr.ID ]) + " tries remaining", plr, COL_CMDERROR );
			}
		}
	}
	else
		MessagePlayer( "You are already logged in." plr, COL_CMDERROR );
}

function DoRegister( plr, pass )
{
	if ( pass )
	{
		MessagePlayer( "Thank you for registering with us. Your password is '" + pass + "', dont forget it!", plr );
		
		SetPassword( plr.Name, pass );
		SetPlayerLevel( plr.Name, LVL_REGISTERED );
		
		SetPlayerIP( plr.Name, plr.IP );
		
		g_loggedIn[ plr.ID ] = true;
		
		SaveAccountHashes();
	}
	else
		MessagePlayer( "Invalid arguments (/register <pass>)", plr );
}

function SetPassword( name, pass )
{
	g_hashPasswords.Add( name.tolower(), MD5( pass ) );
}

function GetPassword( name )
{
	return g_hashPasswords.Get( name.tolower() );
}

function GetPlayerLevel( plr )
{
	if ( g_loggedIn[ plr.ID ] )
	{
		local level = g_hashLevels.Get( plr.Name.tolower() );
		if ( level != null ) 
			return level;
	}
	
	return LVL_UNREGISTERED;
}

function SetPlayerLevel( name, level )
{
	if ( level == LVL_UNREGISTERED )
		g_hashLevels.Del( name.tolower() );
	else
		g_hashLevels.Add( name.tolower(), level );
		
	SaveAccountHashes();
}

function GetPlayerIP( name )
{
	return g_hashIPs.Get( name.tolower() );
}

function SetPlayerIP( name, ip )
{
	g_hashIPs.Add( name.tolower(), ip );
}

function GetAutologin( name )
{
	local autologin = g_hashAutologin.Get( name.tolower() );
	if ( autologin != null )
		return autologin;
	
	return 1;
}

function SetAutologin( name, autologin )
{
	if ( autologin == 1 )
		g_hashAutologin.Del( name.tolower() );
	else
		g_hashAutologin.Add( name.tolower(), autologin );
}

function loginKick( plr )
{
	Message( "Kicking " + plr.Name + " (Login Timeout)" );
	KickPlayer( plr );
}

function DoLoginCheck( plr )
{
	if ( ( GetPlayerIP( plr.Name ) == plr.IP ) && ( GetAutologin( plr.Name ) == 1 ) )
	{
		// Auto-login
		// This goes here else it will say your a level -1
		g_loggedIn[ plr.ID ] = true;
		
		local level = GetPlayerLevel( plr );
		if ( level == LVL_REGISTERED )
			MessagePlayer( "You have been automatically logged in.", plr );
		else
			MessagePlayer( "You have been automatically logged in (Level: " + level + ").", plr );
		
	}
	else
	{
		MessagePlayer( "This nickname is registered. You must login (/login <pass>)", plr );
		g_loginTimers[ plr.ID ] = NewTimer( "loginKick", 10000, 1, plr );
	}
}

function ProcessAccountPlayerJoin( plr )
{
	// Check if the name is banned
	foreach ( name in g_bannedNames )
	{
		if ( name == plr.Name.tolower() )
		{
			MessagePlayer( "You have an invalid name, please change it.", plr, COL_CMDERROR );
			KickPlayer( plr );
			return;
		}
	}
	
	// Here as a precautionary measure incase something fucks up!
	g_loggedIn[ plr.ID ] = false;
	
	// Reset the login attempts
	g_LoginAttempts[ plr.ID ] = 0;
	
	if ( GetPassword( plr.Name ) )
	{
		// User has a registered account
		MessagePlayer( "Welcome back " + plr.Name, plr );
		
		DoLoginCheck( plr );
	}
	else
	{
		MessagePlayer( "Welcome to the server, " + plr.Name, plr );
		MessagePlayer( "Please register your nickname using '/register <pass>'", plr );
		
		g_loggedIn[ plr.ID ] = true;
		
	}	
}

function ProcessAccountPlayerPart( plr )
{
	// Log the player out
	g_loggedIn[ plr.ID ] = false;
	
	// Kill any timers that might exist
	local timer = g_loginTimers[ plr.ID ];
	if ( timer )
		timer.Delete();
}

function ProcessAccountCommands( plr, level, cmd, args )
{
	if ( cmd == "register" )
	{
		if ( level == LVL_UNREGISTERED )
		{
			if ( GetPassword( plr.Name ) == null )
			{
				DoRegister( plr, args );
			}
			else MessagePlayer( "This nickname is already registered. Please login", plr, COL_CMDERROR );
		}
		else MessagePlayer( "You are already registered.", plr, COL_CMDERROR );
		
		return true;
	} // End 'register' command
	
	else if ( cmd == "login" )
	{
		if ( GetPassword( plr.Name ) != null )
		{
			DoLogin( plr, args );
		}
		else MessagePlayer( "This account is not registered. Register with /register <pass>", plr, COL_CMDERROR );
		
		return true;
	} // End 'login' command
	else
	{
		if ( ( level > LVL_UNREGISTERED ) && ( g_loggedIn[ plr.ID ] ) )
		{
			// The following commands wont be processed unless they are registered and logged in
			if ( cmd == "logout" )
			{
				g_loggedIn[ plr.ID ] = false;
				
				SaveHashes();
				
				MessagePlayer( "You have been logged out.", plr );
				
				return true;
			}
			else if ( cmd == "autologin" )
			{
				if ( args )
				{
					if ( args == "on" )
					{
						if ( GetAutologin( plr.Name ) == 0 )
						{
							MessagePlayer( "You have activated autologin based on your IP", plr );
							
							SetAutologin( plr.Name, 1 );
							SetPlayerIP( plr.Name, plr.IP );
							
							SaveAccountHashes();
						}
						else
							MessagePlayer( "Autologin is already enabled for this account", plr, COL_CMDERROR );
					}
					else if ( args == "off" )
					{
						if ( GetAutologin( plr.Name ) == 1 )
						{
							MessagePlayer( "You have deactivated autologin", plr );
							
							SetAutologin( plr.Name, 0 );
							
							SaveAccountHashes();
						}
						else
							MessagePlayer( "Autologin is already disabled for this account", plr, COL_CMDERROR );
					}
					else
						MessagePlayer( "Invalid arguments (/autologin <on/off>)", plr, COL_CMDERROR );
				}
				else
					MessagePlayer( "Invalid arguments (/autologin <on/off>)", plr, COL_CMDERROR );
				
				return true;
			}
		}
	}
	
	return false;
}
